#ifndef DATABASE_HASHOBJECT_H
#define DATABASE_HASHOBJECT_H

#include "Object.hpp"

#include <functional>
#include <unordered_map>
#include <vector>

namespace DBServer
{
namespace Database
{

class HashObject : public Object {
public:
    using Callback = std::function<void(HashObject&, CommandRequest&&, CommandRespond&)>;
    
    HashObject()
    :Object(HASH_TYPE)
    {}
    ~HashObject() = default;

    void command_excute(CommandRespond&, CommandRequest&&, com_func_t&);

public:
    /**
     * the command of HashObject:
     * 1.GET        KEY                         // get all of element in the hash map
     * 2.HADD       KEY     VALUE   VALUE       // insert a key-value entry into the hash map
     * 3.HSIZE      KEY                         // get the number of the hash map
     * 4.HEXIST     KEY     VALUE               // check the specified entry is in the hash map or not
     * 5.HREMOVE    KEY     VALUE               // remove the specified entry from the hash map
     * 
    */
    inline auto get() -> std::vector<std::pair<std::string, std::string>>
    {
        std::vector<std::pair<std::string, std::string>> data_list;
        for (auto entry : hash_map)
        {
            data_list.push_back(entry);
        }
        return data_list;
    }

    inline auto hadd(std::string&& key, std::string&& value) -> bool
    {
        auto iter = hash_map.find(key);
        if (iter != hash_map.end())
        {
            return false;
        }
        hash_map.insert(std::make_pair<std::string, std::string>(std::move(key), std::move(value)));
        return true;
    }

    inline auto hsize() -> int
    {
        return hash_map.size();
    }

    inline auto hexist(std::string&& key, std::pair<std::string, std::string>& entry) -> bool
    {
        auto iter = hash_map.find(key);
        if (iter == hash_map.end())
        {
            return false;
        }
        entry.first = iter->first;
        entry.second = iter->second;
        return true;
    }

    inline auto hremove(std::string&& key) -> bool
    {
        auto iter = hash_map.find(key);
        if (iter == hash_map.end())
        {
            return false;
        }
        hash_map.erase(key);
        return true;
    }

private:
    std::unordered_map<std::string, std::string> hash_map;
    static std::unordered_map<int, Callback> cb_table;
};
    
} // namespace DataBase
} // namespace DBServer


#endif